import { useEffect, useRef, useState } from 'react';
import { getShellApi, getToken } from './utils/client';
import { Terminal } from 'xterm';
import "xterm/css/xterm.css";
import { useSize } from 'ahooks';
import { FitAddon } from 'xterm-addon-fit';
import { Button, Card, Form, Input, Select, message } from 'antd';
import { SearchAddon } from 'xterm-addon-search';
import { writeText, readText } from '@tauri-apps/api/clipboard';
import themes from "./themes/index";
import CommandModal from './CommandModal';
import { BookOutlined } from '@ant-design/icons';

type ThemeName = keyof (typeof themes);

export interface ShellPanelProps {
    curClientId: string;
    curShellId: string;
}

function ShellPanel(props: ShellPanelProps) {
    const termRef = useRef<HTMLDivElement | null>(null);
    const termSize = useSize(termRef);
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    const [_termInit, setTermInit] = useState(false);
    const [shellTerm, setShellTerm] = useState<Terminal | null>(null);
    const [fitAddon, setFitAddon] = useState<FitAddon | null>(null);
    const [searchAddon, setSearchAddon] = useState<SearchAddon | null>(null);
    const [searchText, setSearchText] = useState("");

    const [fontSize, setFontSize] = useState(14);
    const [theme, setTheme] = useState<ThemeName>("Atom");

    const [showCmdModal,setShowCmdModal] = useState(false);

    const readResponse = async (term: Terminal) => {
        const api = getShellApi();
        // eslint-disable-next-line no-constant-condition
        while (true) {
            try {
                const res = await api.shellReadPost({
                    shellClosePostRequest: {
                        token: getToken(),
                        id: props.curClientId,
                        shellId: props.curShellId,
                    },
                });
                if (res == "") {
                    continue;
                } else {
                    const binString = atob(res);
                    term.write(binString);
                }
            } catch (e) {
                console.log(e);
                break;
            }
        }
    };

    const writeData = async (key: string) => {
        const api = getShellApi();
        api.shellWritePost({
            shellWritePostRequest: {
                token: getToken(),
                id: props.curClientId,
                shellId: props.curShellId,
                data: btoa(key),
            }
        });
    }

    const adjustTerm = async () => {
        if (shellTerm == null || fitAddon == null) {
            return;
        }
        fitAddon.fit();
        const api = getShellApi();
        api.shellChangePost({
            shellChangePostRequest: {
                token: getToken(),
                id: props.curClientId,
                shellId: props.curShellId,
                width: shellTerm.cols,
                height: shellTerm.rows,
            },
        });
    };

    const initTerm = () => {
        if (termRef.current == null) {
            return;
        }
        const term = new Terminal();
        term.onKey(ev => writeData(ev.key));
        term.open(termRef.current);
        termRef.current.addEventListener("contextmenu", ev => {
            ev.preventDefault();
            ev.stopPropagation();
        });
        term.options.fontSize = fontSize;
        term.options.theme = themes[theme];
        const fitAddon = new FitAddon();
        term.loadAddon(fitAddon);
        readResponse(term);
        setShellTerm(term);
        setFitAddon(fitAddon);

        const sAddon = new SearchAddon();
        setSearchAddon(sAddon);
        term.loadAddon(sAddon);
    };

    useEffect(() => {
        if (termRef !== null && termRef.current !== null) {
            setTermInit(init => {
                if (init) {
                    return init;
                }
                initTerm();
                return true;
            });
        }
    }, [termRef]);

    useEffect(() => {
        adjustTerm();
    }, [termSize, shellTerm]);

    return (
        <Card bodyStyle={{ padding: "0px 0px" }} bordered={false}
            title={
                <>
                    {termSize !== undefined && termSize.width > 950 && (
                        <Form layout='inline'>
                            <Form.Item label="搜索">
                                <Input value={searchText} onChange={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    setSearchText(e.target.value.trim());
                                }} allowClear />
                            </Form.Item>
                            <Form.Item>
                                <Button onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    searchAddon?.findNext(searchText);
                                }} disabled={searchText == ""}>搜索</Button>
                            </Form.Item>
                        </Form>
                    )}
                </>
            }
            extra={
                <Form layout='inline'>
                    {termSize !== undefined && termSize.width > 700 && (
                        <>
                            <Form.Item label="字体大小">
                                <Select style={{ width: "80px" }} value={fontSize} onChange={value => {
                                    setFontSize(value);
                                    if (shellTerm != null) {
                                        shellTerm.options.fontSize = value;
                                    }
                                }}>
                                    {[10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40].map(item => (
                                        <Select.Option key={item} value={item}>{item}</Select.Option>
                                    ))}
                                </Select>
                            </Form.Item>
                            <Form.Item label="风格">
                                <Select style={{ width: "180px" }} value={theme} onChange={value => {
                                    setTheme(value);
                                    if (shellTerm != null) {
                                        shellTerm.options.theme = themes[value];
                                    }
                                }}>
                                    {Object.keys(themes).map(item => (
                                        <Select.Option key={item} value={item as ThemeName}>{item}</Select.Option>
                                    ))}
                                </Select>
                            </Form.Item>
                        </>
                    )}

                    <Form.Item>
                        <Button onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            if (shellTerm != null) {
                                const txt = shellTerm.getSelection();
                                if (txt != "") {
                                    writeText(txt);
                                    message.info("复制成功");
                                }
                            }
                        }}>复制</Button>
                    </Form.Item>
                    <Form.Item>
                        <Button onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            readText().then(txt => {
                                if (txt == null || txt == "") {
                                    return;
                                }
                                writeData(txt);
                                console.log(txt);
                                message.info("粘贴成功");
                            });
                        }}>粘贴</Button>
                    </Form.Item>
                    <Form>
                        <Button onClick={e=>{
                            e.stopPropagation();
                            e.preventDefault();
                            setShowCmdModal(true);
                        }}><BookOutlined /></Button>
                    </Form>
                </Form>
            }>
            <div style={{ width: "calc(100vw - 300px)", height: "calc(100vh - 96px)" }} ref={termRef} />
            {showCmdModal == true && (
                <CommandModal onCancel={()=>setShowCmdModal(false)} />
            )}
        </Card>
    );
}

export default ShellPanel;